package thread.latch;

import thread.Worker;

import java.util.concurrent.CountDownLatch;

/**
 * 这个主要是CountDownLatch的使用【阀门】
 * 一次性线程屏障，只能限制线程一次
 * 主线程等待计数值为0的时候开始执行自己的任务，不必等待子线程任务是否执行完毕【countDown后还有任务的情况下】
 * Executor并不会在核心线程池用完的情况下去创建新的线程去执行剩余任务【达到线程最大数量，暂时不解】
 *
 * @author wei.yang on 2018/8/7
 */
@SuppressWarnings(value = {"Duplicates", "unused"})
public class LatchQueue {

    private static final int DEFAULT_THREAD_NUM = 10;


    private static final int DEFAULT_THREAD_NUM2 = 3;

    public static void main(String[] args) throws InterruptedException {
        latchType1();
        // latchType2();
    }

    /**
     * 类型1:
     * 屏障数小于线程数【看不出屏障效果，因为CountDownLatch已经拦截够了数量为屏障数的线程，剩下的并不关心】
     */
    private static void latchType1() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        for (int i = 0; i < DEFAULT_THREAD_NUM; i++) {
            Worker.getWorker().execute(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "\t" + "start" + "\t" + System.currentTimeMillis());
                    Thread.sleep(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 计数器更新【减操作】
                    latch.countDown();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "\t" + "end  " + "\t" + System.currentTimeMillis());
                }
            });
        }
        // 让主线程等待计数器归零,然后再做其他的事情【countDown值为0的时候主线程就可以开始跑了，不用等待子线程任务是否结束】
        latch.await();
        Worker.getWorker().shutdown();
        //
        System.out.println("main thread ");
    }

    /**
     * 类型1:
     * 屏障数等于线程数
     */
    private static void latchType2() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        for (int i = 0; i < DEFAULT_THREAD_NUM2; i++) {
            Worker.getWorker().execute(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "\t" + "start" + "\t" + System.currentTimeMillis());
                    Thread.sleep(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 计数器更新【减操作】
                    latch.countDown();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "\t" + "end  " + "\t" + System.currentTimeMillis());
                }
            });
        }
        // 让主线程等待计数器归零,然后再做其他的事情【countDown值为0的时候主线程就可以开始跑了，不用等待子线程任务是否结束】
        latch.await();
        Worker.getWorker().shutdown();
        //
        System.out.println("main thread ");
    }
}
